
#include "MSXMLTree.h"
/*
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <comutil.h>
#include "Common/Strings.h"

//-----------------
//--- MSXMLNode ---
//-----------------

MSXMLNode::MSXMLNode(IXMLDOMNode *node)
{
	this->xmlcur = node;
	cur = 0;
	if (xmlcur != NULL)
	{
		xmlcur->get_childNodes(&children);
		xmlcur->get_attributes(&attrs);
	}
	else
	{
		children = NULL;
		attrs = NULL;
	}
	//getting children
	if (children != NULL)
	{
		IXMLDOMNode *temp;
		children->get_length(&chcount);
		chnames = new BSTR[chcount];
		chvals = new char *[chcount];
		for (long i = 0; i < chcount; i++)
		{
			chvals[i] = NULL;
			children->get_item(i, &temp);
			temp->get_baseName(&(chnames[i]));
			temp->Release();
		}
	}
	else
	{
		chcount = 0;
		chnames = NULL;
		chvals = NULL;
	}
	//getting attributes
	if (attrs != NULL)
	{
		IXMLDOMNode *temp;
		attrs->get_length(&attcount);
		attnames = new BSTR[attcount];
		attvals = new char *[attcount];
		for (long i = 0; i < attcount; i++)
		{
			attvals[i] = NULL;
			attrs->get_item(i, &temp);
			temp->get_baseName(&(attnames[i]));
			temp->Release();
		}
	}
	else
	{
		attcount = 0;
		attnames = NULL;
		attvals = NULL;
	}
}

IXMLDOMNode *MSXMLNode::getChild(const char *name)
{
	if (children != NULL)
	{
		_bstr_t n = _bstr_t(name);
		for (int i = 0; i < chcount; i++)
			if (n.operator ==(chnames[i]))
			{
				IXMLDOMNode *temp;
				children->get_item(i, &temp);
				this->val = &(chvals[i]);
				return temp;
			}
	}
	return NULL;
}

IXMLDOMNode *MSXMLNode::getAttribulte(const char *name)
{
	if (attrs != NULL)
	{
		_bstr_t n = _bstr_t(name);
		for (int i = 0; i < attcount; i++)
			if (n.operator ==(attnames[i]))
			{
				IXMLDOMNode *temp;
				attrs->get_item(i, &temp);
				this->val = &(attvals[i]);
				return temp;
			}
	}
	return NULL;
}

bool MSXMLNode::getField(const char *name, const char *&val)
{
	IXMLDOMNode *temp;
	//Is it attribute?
	if ((temp = this->getAttribulte(name)) == NULL)
	{
		//Is it text-child?
		if ((temp = this->getChild(name)) == NULL)
			return false;
		DOMNodeType type;
		temp->get_nodeType(&type);
		if (type != NODE_TEXT && type != NODE_ATTRIBUTE)
		{
			temp->Release();
			return false;
		}
	}
	//Getting text
	if (*this->val == NULL)
	{
		BSTR v;
		temp->get_text(&v);
		_bstr_t vv = _bstr_t(v);
		*(this->val) = (char *)vv;
		::SysFreeString(v);
		temp->Release();
	}
	val = *(this->val);
	return true;
}

IXMLDOMNode *MSXMLNode::getNextChild()
{
	if (cur < chcount)
	{
		IXMLDOMNode *temp;
		children->get_item(cur++, &temp);
		return temp;
	}
	return NULL;
}

IXMLDOMNode *MSXMLNode::release()
{
	//childs
	for (long i = 0; i < chcount; i++)
	{
		if (chnames[i] != NULL)
			::SysFreeString(chnames[i]);
		if (chvals[i] != NULL)
			delete[] chvals[i];
	}
	if (chnames != NULL)
		delete[] chnames;
	if (chvals != NULL)
		delete[] chvals;
	if (children != NULL)
		children->Release();
	//attributes
	for (long i = 0; i < attcount; i++)
	{
		if (attnames[i] != NULL)
			::SysFreeString(attnames[i]);
		if (attvals[i] != NULL)
			delete[] attvals[i];
	}
	if (attnames != NULL)
		delete[] attnames;
	if (attvals != NULL)
		delete[] attvals;
	if (attrs != NULL)
		attrs->Release();
	return xmlcur;
}

MSXMLNode::~MSXMLNode()
{
	IXMLDOMNode *temp = this->release();
	if (temp != NULL)
		temp->Release();
}

//-----------------
//--- MSXMLTree ---
//-----------------

//public

MSXMLTree::MSXMLTree(IXMLDOMDocument *xmldoc, MSXMLNode *cur)
{
	this->xmldoc = xmldoc;
	this->cur = cur;
	isroot = false;
}

MSXMLTree::MSXMLTree()
{
	this->xmldoc = NULL;
	this->cur = NULL;
	isroot = false;
}

//Control actions

void MSXMLTree::assign(int access, const char *filename)
{
	HRESULT hres;
	VARIANT_BOOL issuccess = false;
	VARIANT fn;
	fn.bstrVal = (BSTR)castToWide((string("file://") + filename).c_str());
	//fn.bstrVal = ::SysAllocString(T2OLE(filename));
	//fn.bstrVal = _bstr_t(filename).copy(); //It is memory leak, isn't it?
	//loading
	if (FAILED(hres = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, 
									 IID_IXMLDOMDocument, (void**)&xmldoc)) ||
		FAILED(hres = xmldoc->put_async(VARIANT_TRUE)) ||
		FAILED(hres = xmldoc->load(fn, &issuccess)) ||
		!issuccess)
	{
		delete[] fn.bstrVal;
		throw IOError(Error::LOCAL, "MSXMLTree", "assign", "Cannot load file", hres);
	}
	delete[] fn.bstrVal;
	//getting root
	IXMLDOMNode *xmlcur;
	if (FAILED(hres = xmldoc->get_firstChild(&xmlcur)))
	{
		xmldoc->Release();
		xmldoc = NULL;
		throw IOError(Error::LOCAL, "MSXMLTree", "assign", "Cannot allocate root", hres);
	}
	this->cur = new MSXMLNode(xmlcur);
	trace.push_back(cur);
	isroot = true;
}

void MSXMLTree::close()
{
	//node
	list<MSXMLNode *>::iterator it = trace.end();
	while (it != trace.begin())
	{
		if (*it != NULL)
		{
			delete *it;
		}
		it--;
	}
	trace.clear();
	cur = NULL;
	if (isroot && xmldoc != NULL)
	{
		xmldoc->Release();
		xmldoc = NULL;
		isroot = false;
	}
}

XMLTree &MSXMLTree::getSubXMLTree()
{
	if (cur != NULL)
	{
		//return MSXMLTree(xmldoc, cur);
		//<fix me>
		return *this;
		//</fix me>
	}
	else
		throw Error(Error::LOCAL, "MSXMLTree", "getSubXMLTree", "Not inited");
}

MSXMLTree::~MSXMLTree()
{
	this->close();
}

//ro actions

bool MSXMLTree::openSection(const char *section)
{
	IXMLDOMNode *temp;
	if ((cur != NULL) &&
		(temp = cur->getChild(section)) != NULL)
	{
		DOMNodeType type;
		temp->get_nodeType(&type);
		if (type == NODE_ELEMENT)
			trace.push_back(cur = new MSXMLNode(temp));
		return true;
	}
	return false;
}

bool MSXMLTree::closeSection()
{
	if (trace.size() >= 1)
	{
		cur = *(trace.end()--);
		delete *(trace.end());
		trace.pop_back();
		return true;
	}
	return false;
}

bool MSXMLTree::openNextSection()
{
	IXMLDOMNode *temp;
	if ((cur != NULL) &&
		(temp = cur->getNextChild()) != NULL)
	{
		DOMNodeType type;
		temp->get_nodeType(&type);
		if (type == NODE_ELEMENT)
			trace.push_back(cur = new MSXMLNode(temp));
		return true;
	}
	return false;
}

const char *MSXMLTree::getCurrentSection()
{
	throw Error(Error::FATAL, "MSXMLTree", "getCurrentSection", "Not implemented yet");
}

bool MSXMLTree::getStringAttribute(const char *attr, const char *&val)
{
	if (cur != NULL)
		return cur->getField(attr, val);
	else
		return false;
}
*/